home *** CD-ROM | disk | FTP | other *** search
/ The X-Philes (2nd Revision) / The X-Philes Number 1 (1995).iso / xphiles / hp48_2 / vsrc.tar / voyager7_src / index.c < prev    next >
C/C++ Source or Header  |  1991-02-27  |  16KB  |  873 lines

  1. /*
  2. // Abstract:
  3. //    INDEX---Comment File Indexing
  4. //
  5. //    The Comment File Indexing module handles storing and fetching of
  6. //    address and code comments.
  7. //
  8. // Author:
  9. //    Derek S. Nickel
  10. //
  11. // Creation date:
  12. //    12 November 1990
  13. //
  14. // History:
  15. // V01-001    Derek S. Nickel        12-NOV-1990
  16. //    Original.
  17. //
  18. */
  19.  
  20. #include <stdlib.h>
  21. #include <stdio.h>
  22. #include <string.h>
  23. #include <io.h>
  24. #include <sys\types.h>
  25. #include <sys\stat.h>
  26.  
  27. #include "index.h"
  28. #include "memory.h"
  29. #include "modes.h"
  30. #include "tree.h"
  31.  
  32. typedef struct {
  33.     bin5_t key;
  34.     long value;
  35. } filenode_t;
  36.  
  37. #define MAX_LINE 256
  38. static char cbuf[MAX_LINE];        /* for returned comments */
  39.  
  40. #define BRAVE 0
  41.  
  42. /***********************************************************************
  43.     Messages.
  44. ***********************************************************************/
  45.  
  46. #define vgr__makeidx \
  47. "%%VOYAGER-I-MAKEIDX, making index for %s\n"
  48.  
  49. #define vgr__notyetava \
  50. "%%VOYAGER-I-NOTYETAVA, operation is not yet available\n"
  51.  
  52. #define vgr__merging \
  53. "%%VOYAGER-I-MERGING, merging %s into %s\n"
  54.  
  55. #define vgr__merged \
  56. "%%VOYAGER-I-MERGED, %ld out of %ld comments from %s merged into %s\n"
  57.  
  58. #define vgr__openin \
  59. "%%VOYAGER-E-OPENIN, error opening %s as input\n"
  60.  
  61. #define vgr__readidx \
  62. "%%VOYAGER-I-READIDX, reading index for %s\n"
  63.  
  64. #define vgr__sorted \
  65. "%%VOYAGER-I-SORTTXT, %ld comments written to %s\n"
  66.  
  67. #define vgr__sorting \
  68. "%%VOYAGER-I-SORTTXT, writing %s (sorted)\n"
  69.  
  70. #define vgr__writeidx \
  71. "%%VOYAGER-I-WRITEIDX, writing index for %s\n"
  72.  
  73. #define rms$_fnf \
  74. "-RMS-E-FNF, file not found\n"
  75.  
  76. #if VGR_TRACE & 0x00000001
  77. #define TRACE(t1,t2,t3,t4) { \\
  78.     printf("Trace: "); \\
  79.     printf(t1,t2,t3,t4); \\
  80.     printf("\n"); }
  81. #else
  82. #define TRACE(t1,t2,t3,t4)
  83. #endif
  84.  
  85. /***********************************************************************
  86.     file_open
  87. ***********************************************************************/
  88.  
  89. static FILE *file_open(char *name, char *type)
  90. {
  91.     FILE *ans;
  92.  
  93.     TRACE("opening %s, mode %s", name, type, 0);
  94.  
  95.     ans = fopen(name, type);
  96.  
  97.     if (ans == NULL) {
  98.         printf(vgr__openin, name);
  99.         exit(-1);
  100.     }
  101.  
  102.     return ans;
  103. }
  104.  
  105. /***********************************************************************
  106.     compare_node
  107. ***********************************************************************/
  108.  
  109. static int compare_node(bin5_t *data, node_t **node, char *junk)
  110. {
  111.     int result = 0;
  112.  
  113.     TRACE("comparing %05lX to %05lX", *data, (*node)->key, 0);
  114.  
  115.     if (*data < (*node)->key)
  116.         result = -1;
  117.     else if (*data > (*node)->key)
  118.         result = 1;
  119.     return result;
  120. }
  121.  
  122. /***********************************************************************
  123.     allocate_node
  124. ***********************************************************************/
  125.  
  126. static int allocate_node(bin5_t *key, node_t **node, char *junk)
  127. {
  128.     *node = malloc(sizeof(node_t));
  129.  
  130.     TRACE("allocated node for %05lX at %p", *key, *node, 0);
  131.  
  132.     if (*node == NULL) {
  133.         printf("error allocating node for %05lX\n", *key);
  134.         exit(-1);
  135.     }
  136.  
  137.     (*node)->key = *key;
  138.     (*node)->value = 0;
  139.     (*node)->deleted = 0;
  140.  
  141.     return 1;
  142. }
  143.  
  144. /***********************************************************************
  145.     deallocate_node
  146. ***********************************************************************/
  147.  
  148. static int deallocate_node(node_t *node, char *junk)
  149. {
  150.     TRACE("deallocating node for %05lX at %p", node->key, *node, 0);
  151.     free(node);
  152.  
  153.     return 1;
  154. }
  155.  
  156. /***********************************************************************
  157.     write_one_index
  158. ***********************************************************************/
  159.  
  160. typedef struct _wrtidx_t wrtidx_t;
  161.  
  162. struct _wrtidx_t {
  163.     FILE *f;
  164. };
  165.  
  166. static int write_one_index(node_t *node, wrtidx_t *db)
  167. {
  168.     filenode_t fnode;
  169.  
  170.     TRACE("Node: %p, Key: %05lX, Value: %ld\n",
  171.         node, node->key, node->value );
  172.  
  173.     /*
  174.     // If this node has not been flagged as deleted...
  175.     */
  176.  
  177.     if (!node->deleted) {
  178.         /*
  179.         // Copy data (index info) to file node and write to
  180.         // index file.
  181.         */
  182.  
  183.         fnode.key = node->key;
  184.         fnode.value = node->value;
  185.  
  186.         fwrite(&fnode, sizeof(filenode_t), 1, db->f);
  187.     }
  188.  
  189.     return 1;
  190. }
  191.  
  192. /***********************************************************************
  193.     GetTextLine
  194. ***********************************************************************/
  195.  
  196. char *GetTextLine(text_file_t *tf, bin5_t key)
  197. {
  198.     char *cbufp;
  199.     node_t *node;
  200.     cond_value stat;
  201.  
  202.     /*
  203.     // Get the information for this symbol.
  204.     */
  205.  
  206.     stat = lookup_tree(
  207.         &tf->root,
  208.         &key,
  209.         compare_node,
  210.         &node );
  211.  
  212.     /*
  213.     // If it was found...
  214.     */
  215.  
  216.     if (stat & 1) {
  217.         if (!node->deleted) {
  218.             fseek(tf->f, node->value, SEEK_SET);
  219.             fgets(cbuf, sizeof(cbuf), tf->f);
  220.             cbuf[strlen(cbuf)-1] = '\0';
  221.             cbufp = cbuf+6;
  222.         } else {
  223.             cbuf[0] = '\0';
  224.             cbufp = cbuf;
  225.         }
  226.     } else {
  227.         cbuf[0] = '\0';
  228.         cbufp = cbuf;
  229.     }
  230.  
  231.     return cbufp;
  232. }
  233.  
  234. /***********************************************************************
  235.     DelTextLine
  236. ***********************************************************************/
  237.  
  238. void DelTextLine(text_file_t *tf, bin5_t key)
  239. {
  240.     node_t *node;
  241.     cond_value stat;
  242.     char c;
  243.  
  244.     stat = lookup_tree(
  245.         &tf->root,
  246.         &key,
  247.         compare_node,
  248.         &node );
  249.  
  250.     if (stat & 1) {
  251.         if (!node->deleted) {
  252.             fseek(tf->f, node->value, SEEK_SET);
  253.             fputc('-', tf->f);
  254.             node->deleted = 1;
  255.             tf->changes++;
  256.             tf->count--;
  257.         }
  258.     }
  259. }
  260.  
  261. /***********************************************************************
  262.     AddTextLine
  263. ***********************************************************************/
  264.  
  265. void AddTextLine(text_file_t *tf, bin5_t key, char *cmt)
  266. {
  267.     char *buf[240];
  268.     long p;
  269.     node_t *node;
  270.     cond_value stat;
  271.     char c;
  272.  
  273.     /*
  274.     // Create new entry (or get existing entry).
  275.     */
  276.  
  277.     stat = insert_tree(
  278.         &tf->root,
  279.         &key,
  280.         0,
  281.         compare_node,
  282.         allocate_node,
  283.         &node,
  284.         0 );
  285.  
  286.     /*
  287.     // Mark old comment as deleted.
  288.     */
  289.  
  290.     if (stat == lib$_keyalrins) {
  291.         if (!node->deleted) {
  292.             fseek(tf->f, node->value, SEEK_SET);
  293.             fputc('-', tf->f);
  294.             node->deleted = 1;
  295.             tf->changes++;
  296.             tf->count--;
  297.         }
  298.     }
  299.  
  300.     /*
  301.     // Add the comment to the file and update the node.
  302.     */
  303.  
  304.     fseek(tf->f, 0, SEEK_END);
  305.     node->value = ftell(tf->f);
  306.     fprintf(tf->f, "%05lX %s\n", key, cmt);
  307.     node->deleted = 0;
  308.     tf->changes++;
  309.     tf->count++;
  310. }
  311.  
  312. /***********************************************************************
  313.     merge_text_line
  314. ***********************************************************************/
  315.  
  316. void merge_text_line(text_file_t *tf, bin5_t key, char *cmt)
  317. {
  318.     char *buf[240];
  319.     long p;
  320.     node_t *node;
  321.     cond_value sys_status;
  322.  
  323.     /*
  324.     // Create new entry (or get existing entry).
  325.     */
  326.  
  327.     sys_status = insert_tree(
  328.         &tf->root,
  329.         &key,
  330.         0,
  331.         compare_node,
  332.         allocate_node,
  333.         &node,
  334.         0 );
  335.  
  336.     /*
  337.     // Add new comment only if no existing (undelted) entry.
  338.     */
  339.  
  340.     if ((sys_status != lib$_keyalrins) || (node->deleted)) {
  341.         /*
  342.         // Add the comment to the file and update the node.
  343.         */
  344.  
  345.         fseek(tf->f, 0, SEEK_END);
  346.         node->value = ftell(tf->f);
  347.         fprintf(tf->f, "%05lX %s\n", key, cmt);
  348.         node->deleted = 0;
  349.         tf->changes++;
  350.         tf->count++;
  351.     }
  352. }
  353.  
  354. /***********************************************************************
  355.     read_text_index
  356. ***********************************************************************/
  357.  
  358. static void read_text_index(text_file_t *tf)
  359. {
  360.     FILE *f;
  361.     node_t *node;
  362.     filenode_t fnode;
  363.     cond_value stat;
  364.  
  365.     if (modes.info) printf(vgr__readidx, tf->fnmap);
  366.  
  367.     /*
  368.     // Open the index.
  369.     */
  370.  
  371.     f = file_open(tf->fninx, "rb");
  372.     tf->count = 0;
  373.  
  374.     /*
  375.     // Get the first entry from the index file.
  376.     */
  377.  
  378.     fread(&fnode, sizeof(filenode_t), 1, f);
  379.  
  380.     /*
  381.     // While not end-of-file...
  382.     */
  383.  
  384.     while (!feof(f)) {
  385.         /*
  386.         // Create new entry.
  387.         */
  388.  
  389.         stat = insert_tree(
  390.             &tf->root,
  391.             &fnode.key,
  392.             0,
  393.             compare_node,
  394.             allocate_node,
  395.             &node,
  396.             0 );
  397.  
  398.         /*
  399.         // Update the node.
  400.         */
  401.  
  402.         node->value = fnode.value;
  403.         node->deleted = 0;
  404.  
  405.         /*
  406.         // Count this entry.
  407.         */
  408.  
  409.         tf->count++;
  410.  
  411.         /*
  412.         // Get the next entry from the index file.
  413.         */
  414.  
  415.         fread(&fnode, sizeof(filenode_t), 1, f);
  416.     }
  417.  
  418.     /*
  419.     // Close the index file and clear changes counter.
  420.     */
  421.  
  422.     fclose(f);
  423.     tf->changes = 0;
  424. }
  425.  
  426. /***********************************************************************
  427.     write_text_index
  428. ***********************************************************************/
  429.  
  430. static void write_text_index(text_file_t *tf)
  431. {
  432.     wrtidx_t db;
  433.     cond_value sys_status;
  434.  
  435.     if (modes.info) printf(vgr__writeidx, tf->fnmap);
  436.  
  437.     /*
  438.     // Open the index file.
  439.     */
  440.  
  441.     db.f = file_open(tf->fninx, "wb");
  442.  
  443.     /*
  444.     // Write out the index, skipping deleted entries.
  445.     */
  446.  
  447.     sys_status = traverse_tree(
  448.         &tf->root,
  449.         write_one_index,
  450.         &db );
  451.  
  452.     /*
  453.     // Close the index file.
  454.     */
  455.  
  456.     fclose(db.f);
  457.  
  458.     /*
  459.     // Index file is now up-to-date.
  460.     */
  461.  
  462.     tf->changes = 0;
  463. }
  464.  
  465. /***********************************************************************
  466.     make_text_index
  467. ***********************************************************************/
  468.  
  469. static void make_text_index(text_file_t *tf)
  470. {
  471.     char buf[240];
  472.     long wh;
  473.     node_t *node;
  474.     bin5_t key;
  475.     cond_value stat;
  476.  
  477.     if (modes.info) printf(vgr__makeidx, tf->fnmap);
  478.  
  479.     /*
  480.     // Reset changes counter.  If any comments are found, this will
  481.     // be increamented, causing the index to be updated upon exit.
  482.     */
  483.  
  484.     tf->changes = 0;
  485.     tf->count = 0;
  486.  
  487.     /*
  488.     // Reset to beginning of file.
  489.     */
  490.  
  491.     fseek(tf->f, 0L, SEEK_SET);
  492.  
  493.     while (!feof(tf->f)) {
  494.         /*
  495.         // Get the text and position of the next comment.
  496.         */
  497.  
  498.         wh = ftell(tf->f);
  499.         if (!fgets(buf, sizeof(buf), tf->f)) break;
  500.         buf[5] = '\0';
  501.  
  502.         /*
  503.         // If this comment has not been flagged as deleted...
  504.         */
  505.  
  506.         if (*buf != '-') {
  507.             /*
  508.             // Count this comment.
  509.             */
  510.  
  511.             tf->changes++;
  512.             tf->count++;
  513.  
  514.             /*
  515.             // Convert address from hex string to integer.
  516.             */
  517.  
  518.             key = str2adr(buf, 0);
  519.  
  520.             /*
  521.             // Create a new index entry.
  522.             */
  523.  
  524.             stat = insert_tree(
  525.                 &tf->root,
  526.                 &key,
  527.                 0,
  528.                 compare_node,
  529.                 allocate_node,
  530.                 &node,
  531.                 0 );
  532.  
  533.             /*
  534.             // Update the node.
  535.             */
  536.  
  537.             node->value = wh;
  538.             node->deleted = 0;
  539.         }
  540.     }
  541. }
  542.  
  543. /***********************************************************************
  544.     destroy_text_index
  545. ***********************************************************************/
  546.  
  547. static void destroy_text_index(text_file_t *tf)
  548. {
  549.     cond_value stat;
  550.  
  551.     TRACE("destroying index %s", tf->fninx, 0, 0);
  552.  
  553.     /*
  554.     // Get rid of all the nodes in the index.
  555.     */
  556.  
  557.     stat = post_order_traversal(
  558.         &tf->root,
  559.         deallocate_node,
  560.         NULL );
  561.  
  562.     tf->root = NULL;
  563. }
  564.  
  565. /***********************************************************************
  566.     open_text_file
  567. ***********************************************************************/
  568.  
  569. void open_text_file(text_file_t *tf, char *filename, char *code)
  570. {
  571.     /*
  572.     // Open/create the comment file.
  573.     */
  574.  
  575.     strcpy(tf->fnmap, filename);
  576.     strcat(tf->fnmap, ".");
  577.     strcat(tf->fnmap, code);
  578.  
  579.     if (access(tf->fnmap,0)) {
  580.         FILE *f = file_open(tf->fnmap, "wt");
  581.         fclose(f);
  582.     }
  583.  
  584.     tf->f = file_open(tf->fnmap, "r+t");
  585.  
  586.     /*
  587.     // Read/make the comment file's index.
  588.     */
  589.  
  590.     strcpy(tf->fninx, tf->fnmap);
  591.     strcat(tf->fninx, "X");
  592.  
  593.     /*
  594.     // Does the index exist?
  595.     */
  596.  
  597.     if (access(tf->fninx,0)) {
  598.         /*
  599.         // No index.
  600.         */
  601.  
  602.         make_text_index(tf);
  603.  
  604.     } else {
  605.         struct stat map_stat;
  606.         struct stat inx_stat;
  607.  
  608.         /*
  609.         // Compare the modification times between the
  610.         // comment file and its index.
  611.         */
  612.  
  613.         stat(tf->fnmap, &map_stat);
  614.         stat(tf->fninx, &inx_stat);
  615.  
  616.         if (inx_stat.st_mtime < map_stat.st_mtime) {
  617.             /*
  618.             // Index is out-of-date (text file has been
  619.             // modified.
  620.             */
  621.  
  622.             make_text_index(tf);
  623.  
  624.         } else {
  625.             /*
  626.             // Index is up-to-date.
  627.             */
  628.  
  629.             read_text_index(tf);
  630.         }
  631.     }
  632. }
  633.  
  634. /***********************************************************************
  635.     close_text_file
  636. ***********************************************************************/
  637.  
  638. void close_text_file(text_file_t *tf)
  639. {
  640.     fclose(tf->f);
  641.     if (tf->changes) write_text_index(tf);
  642.     destroy_text_index(tf);
  643. }
  644.  
  645. /***********************************************************************
  646.     open_memory_file
  647. ***********************************************************************/
  648.  
  649. void open_memory_file(FILE **xfile, char *module)
  650. {
  651.     char fname[_MAX_PATH];
  652.  
  653.     strcpy(fname, module);
  654.     strcat(fname, ".MEM");
  655.  
  656.     *xfile = file_open(fname, "r+t");
  657. }
  658.  
  659. /***********************************************************************
  660.     close_memory_file
  661. ***********************************************************************/
  662.  
  663. void close_memory_file(FILE *xfile)
  664. {
  665.     fclose(xfile);
  666. }
  667.  
  668. /***********************************************************************
  669.     write_one_line
  670. ***********************************************************************/
  671.  
  672. typedef struct _sortdata_t sortdata_t;
  673.  
  674. struct _sortdata_t {
  675.     FILE *f;
  676.     text_file_t *tf;
  677.     long count;
  678. };
  679.  
  680. static int write_one_line(node_t *node, sortdata_t *db)
  681. {
  682.     char *cbufp;
  683.  
  684.     TRACE("(sort) Node: %p, Key: %05lX, Value: %ld\n",
  685.         node, node->key, node->value );
  686.  
  687.     if (!node->deleted) {
  688.         fseek(db->tf->f, node->value, SEEK_SET);
  689.         fgets(cbuf, sizeof(cbuf), db->tf->f);
  690.         cbuf[strlen(cbuf)-1] = '\0';
  691.         cbufp = cbuf+6;
  692.         fprintf(db->f, "%05lX %s\n", node->key, cbufp);
  693.         db->count++;
  694.     };
  695.  
  696.     return 1;
  697. }
  698.  
  699. /***********************************************************************
  700.     sort_text_file
  701. ***********************************************************************/
  702.  
  703. void sort_text_file(text_file_t *tf, char *filename, char *code,
  704.     char *tmpnam, int *idx)
  705. {
  706.     cond_value stat;
  707.     char newfile[_MAX_PATH];
  708.     char oldfile[_MAX_PATH];
  709.     char t[4];
  710.     sortdata_t db;
  711.  
  712.     if (modes.info) printf(vgr__sorting, tf->fnmap);
  713.  
  714.     /*
  715.     // Build intermediate file names.
  716.     */
  717.  
  718.     sprintf(t, "%03hX", *idx);
  719.     (*idx)++;
  720.     strcpy(newfile, tmpnam);
  721.     strcat(newfile, ".");
  722.     strcat(newfile, t);
  723.  
  724. #if !BRAVE
  725.     sprintf(t, "%03hX", *idx);
  726.     (*idx)++;
  727.     strcpy(oldfile, tmpnam);
  728.     strcat(oldfile, ".");
  729.     strcat(oldfile, t);
  730. #endif
  731.  
  732.     /*
  733.     // Create the new comment file with a temporary name.
  734.     */
  735.  
  736.     db.f = file_open(newfile, "wt");
  737.  
  738.     /*
  739.     // Store pointer to the text file.
  740.     */
  741.  
  742.     db.tf = tf;
  743.  
  744.     /*
  745.     // Clear comments count.
  746.     */
  747.  
  748.     db.count = 0;
  749.  
  750.     /*
  751.     // Write out the comments in sorted order, skipping deleted
  752.     // comments.
  753.     */
  754.  
  755.     stat = traverse_tree(
  756.         &tf->root,
  757.         write_one_line,
  758.         &db );
  759.  
  760.     /*
  761.     // Close all files.
  762.     */
  763.  
  764.     fclose(db.f);
  765.     fclose(tf->f);
  766.  
  767.     /*
  768.     // Remove (or rename) the old comment file.
  769.     */
  770.  
  771. #if BRAVE
  772.     remove(tf->fnmap);
  773. #else
  774.     rename(tf->fnmap, oldfile);
  775. #endif
  776.  
  777.     /*
  778.     // Rename the new comment file.
  779.     */
  780.  
  781.     rename(newfile, tf->fnmap);
  782.  
  783.     /*
  784.     // Display sort statistics.
  785.     */
  786.  
  787.     printf(vgr__sorted, db.count, tf->fnmap);
  788.  
  789.     /*
  790.     // Open the new comment file.
  791.     */
  792.  
  793.     tf->f = file_open(tf->fnmap, "r+t");
  794.  
  795.     /*
  796.     // Recreate the index.
  797.     */
  798.  
  799.     destroy_text_index(tf);
  800.     make_text_index(tf);
  801. }
  802.  
  803. /***********************************************************************
  804.     merge_text_file
  805. ***********************************************************************/
  806.  
  807. void merge_text_file(text_file_t *tf, char *new_module, char *code)
  808. {
  809.     FILE *ifile;
  810.     char ibuf[MAX_LINE];
  811.     char *cmt;
  812.     long merges;
  813.     long attempts;
  814.     bin5_t key;
  815.     char *nl_pos;
  816.  
  817.     if (modes.info) printf(vgr__merging, new_module, tf->fnmap);
  818.  
  819.     /*
  820.     // Save current count (for merged count).
  821.     */
  822.  
  823.     merges = tf->changes;
  824.     attempts = 0;
  825.  
  826.     /*
  827.     // Open the input file.
  828.     */
  829.  
  830.     ifile = file_open(new_module, "rt");
  831.  
  832.     /*
  833.     // Read from the input and merge in new comments.
  834.     */
  835.  
  836.     while (!feof(ifile)) {
  837.         if (fgets(ibuf,MAX_LINE,ifile)) {
  838.             key = strtoul(ibuf,&cmt,16);
  839.  
  840.             if (*cmt) {
  841.                 /* skip leading blank or separator */
  842.                 cmt++;
  843.                 while (*cmt == ' ')
  844.                     cmt++;
  845.  
  846.                 nl_pos = strrchr(cmt,'\n');
  847.                 if (nl_pos) *nl_pos = '\0';
  848.  
  849.                 attempts++;
  850.                 merge_text_line(tf, key, cmt);
  851.             }
  852.         }
  853.     }
  854.  
  855.     /*
  856.     // Close the input file.
  857.     */
  858.  
  859.     fclose(ifile);
  860.  
  861.     /*
  862.     // Calculate number of comments merged in.
  863.     */
  864.  
  865.     merges = tf->changes - merges;
  866.  
  867.     /*
  868.     // Display merge statistics.
  869.     */
  870.  
  871.     printf(vgr__merged, merges, attempts, new_module, tf->fnmap);
  872. }
  873.